//
//  TFLabel.swift
//  XS微博
//
//  Created by 王小帅 on 2016/12/28.
//  Copyright © 2016年 王小帅. All rights reserved.
//

import UIKit

// 选择网址代理
@objc protocol TFLabelDelegate: NSObjectProtocol {
    
    @objc optional func tFLabelDidSelectedUrlString(label: TFLabel, urlString: String)
}

class TFLabel: UILabel {
    
    // 代理
    weak var delegate: TFLabelDelegate?
    
    // 重写属性方法 监听文本变化随时接管 系统文本
    override var text: String? {
        didSet{
            prepareTextContent()
        }
    }
    
    override var attributedText: NSAttributedString? {
        didSet{
            prepareTextContent()
        }
    }
    
    override var font: UIFont! {
        didSet{
            prepareTextContent()
        }
    }
    
    override var textColor: UIColor! {
        didSet{
            prepareTextContent()
        }
    }
    
    // 重写初始化方法 接管系统文本
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        prepareTextSystem()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        prepareTextSystem()
    }
    
    // textkit 接管系统文字准备
    /// 文本存储
    lazy var textStorage = NSTextStorage()
    /// 管理字形
    lazy var layoutManager = NSLayoutManager()
    /// 文本绘制区域
    lazy var textContainer = NSTextContainer()
    
    
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        // 设置绘制区域
        textContainer.size = bounds.size
    }
    
    
    // 接收系统文本后 调用绘制方法来重新绘制
    override func drawText(in rect: CGRect) {
        // 调用此方法 默认使用系统方法绘制
        //        super.drawText(in: rect)
        
        // 绘制背景和文字
        let range = NSRange(location: 0, length: textStorage.length)
        // 先绘制背景
        layoutManager.drawBackground(forGlyphRange: range, at: CGPoint())
        // 在绘制字体
        layoutManager.drawGlyphs(forGlyphRange: range, at: CGPoint())
    }
    
    
    // 用户交互
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        // 获取点击地点
        guard let localtion = touches.first?.location(in: self) else {
            return
        }
        
        // 获取该点 在文本中的位置
        let idx = layoutManager.glyphIndex(for: localtion, in: textContainer)
        
        // 判断该位置是否在url中
        for r in urlRanges ?? [] {
            if NSLocationInRange(idx, r) {
                // 高亮显示
                setHightLight(isHL: true, r: r)
                
            }else {
                // 这里其实是进入微博详细的 先不做了
            }
        }
        
    }
    
    // 结束交互
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        // 获取点击地点
        guard let localtion = touches.first?.location(in: self) else {
            return
        }
        
        // 获取该点 在文本中的位置
        let idx = layoutManager.glyphIndex(for: localtion, in: textContainer)
        
        // 判断该位置是否在url中
        for r in urlRanges ?? [] {
            if NSLocationInRange(idx, r) {
                // 高亮显示
                setHightLight(isHL: true, r: r)
                // 执行代理方法
                let urlStr = (textStorage.string as NSString).substring(with: r)
                delegate?.tFLabelDidSelectedUrlString?(label: self, urlString: urlStr)
                
            }else {
                // 这里其实是进入微博详细的 先不做了
                setHightLight(isHL: false, r: r)
                
            }
        }
        
    }
    
    // 移动
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        // 获取点击地点
        guard let localtion = touches.first?.location(in: self) else {
            return
        }
        
        // 获取该点 在文本中的位置
        let idx = layoutManager.glyphIndex(for: localtion, in: textContainer)
        
        // 判断该位置是否在url中
        for r in urlRanges ?? [] {
            if NSLocationInRange(idx, r) {
                // 高亮显示
                setHightLight(isHL: true, r: r)
                
            }else {
                // 这里其实是进入微博详细的 先不做了
                setHightLight(isHL: false, r: r)
                
            }
        }
    }
    
    
    /// 是否高亮现实网址链接
    func setHightLight(isHL: Bool, r: NSRange) {
        
        if isHL {
            // 高亮显示
            textStorage.addAttributes([NSForegroundColorAttributeName: UIColor.orange
                
                ], range: r)
            
        }else {
            // 不高亮
            textStorage.addAttributes([NSForegroundColorAttributeName: UIColor.blue
                                       ], range: r)
        }
        
        setNeedsDisplay()
    }
}


// MARK: - 获取url的range数组
extension TFLabel {
    
    var urlRanges: [NSRange]? {
        
        // 正则匹配所有网址
        let pattern = "[a-zA-Z]*://[a-zA-z0-9/\\.]*"
        
        guard let regx = try? NSRegularExpression(pattern: pattern, options: []) else {
            return nil // 正则匹配失败返回
        }
        
        // 获取matchs
        let matchs = regx.matches(in: textStorage.string, options: [], range: NSRange(location: 0, length: textStorage.length))
        
        // 返回的结果数组
        var result = [NSRange]()
        
        for m in matchs {
            let r = m.rangeAt(0)
            result.append(r)
        }
        
        return result
    }
}


// MARK: - 接管系统文字
extension TFLabel {
    
    /// 准备系统文本系统
    func prepareTextSystem() {
        
        // 接管系统文本
        prepareTextContent()
        // 设置关系
        textStorage.addLayoutManager(layoutManager)
        layoutManager.addTextContainer(textContainer)
        
    }
    
    /// 接管系统文本
    func prepareTextContent() {
        
        // 开启交互
        isUserInteractionEnabled = true
        
        // 判断文本存储的属性
        if let attrText = attributedText {
            textStorage.setAttributedString(attrText)
            
        }else if let text = text {
            textStorage.setAttributedString(NSAttributedString(string: text))
            
        }else {
            textStorage.setAttributedString(NSAttributedString(string: ""))
        }
        
        // 绘制网址
        for r in urlRanges ?? [] {
            // 网址默认是黄色
            setHightLight(isHL: false, r: r)
        }
    }
}
